Una guida completa alla Content Security Policy (CSP) e agli altri header di sicurezza frontend, per proteggere le applicazioni web dagli attacchi e migliorare la sicurezza degli utenti a livello globale.
Header di Sicurezza Frontend: Padroneggiare la Content Security Policy (CSP)
Nel panorama digitale odierno, dove le applicazioni web sono sempre più complesse e interconnesse, la protezione contro le minacce alla sicurezza è di fondamentale importanza. Sebbene la sicurezza del backend riceva spesso un'attenzione significativa, quella del frontend è altrettanto cruciale. Gli header di sicurezza frontend agiscono come prima linea di difesa, fornendo un meccanismo per istruire il browser su come comportarsi e proteggere gli utenti da vari attacchi. Tra questi header, la Content Security Policy (CSP) si distingue come uno strumento potente per mitigare una vasta gamma di rischi.
Cosa sono gli Header di Sicurezza Frontend?
Gli header di sicurezza frontend sono header di risposta HTTP che un server web invia al browser. Questi header contengono istruzioni su come il browser dovrebbe gestire il contenuto che riceve. Aiutano a prevenire attacchi comuni come:
- Cross-Site Scripting (XSS): Iniezione di script dannosi in siti web affidabili.
- Clickjacking: Indurre gli utenti a fare clic su qualcosa di diverso da ciò che percepiscono.
- Man-in-the-Middle Attacks: Intercettazione della comunicazione tra l'utente e il server.
Alcuni dei più importanti header di sicurezza frontend includono:
- Content Security Policy (CSP): Definisce le fonti da cui il browser è autorizzato a caricare risorse.
- Strict-Transport-Security (HSTS): Forza il browser a usare HTTPS per tutte le comunicazioni con il sito web.
- X-Frame-Options: Impedisce che il sito web venga incorporato in un iframe, mitigando gli attacchi di clickjacking.
- X-XSS-Protection: Abilita il filtro XSS integrato del browser. (Nota: Spesso superato dalla CSP, ma può ancora fornire un livello di difesa).
- Referrer-Policy: Controlla la quantità di informazioni sul referrer inviate con le richieste.
- Feature-Policy (ora Permissions-Policy): Permette agli sviluppatori di abilitare e disabilitare selettivamente le funzionalità e le API del browser.
Approfondimento sulla Content Security Policy (CSP)
La Content Security Policy (CSP) è un header di risposta HTTP che controlla le risorse che l'user agent è autorizzato a caricare per una determinata pagina. In sostanza, crea una "lista bianca" di fonti di contenuto approvate, riducendo significativamente il rischio di attacchi XSS. Definendo esplicitamente le origini da cui possono essere caricate risorse come script, fogli di stile, immagini e font, la CSP rende molto più difficile per gli aggressori iniettare codice dannoso nel tuo sito web.
Come funziona la CSP
La CSP funziona fornendo al browser un elenco di fonti approvate per diversi tipi di contenuto. Quando il browser incontra una risorsa che viola la CSP, blocca la risorsa e segnala la violazione. Questo meccanismo di blocco impedisce l'esecuzione di codice dannoso, anche se un aggressore riesce a iniettarlo nell'HTML.
Direttive CSP
Le direttive CSP sono i componenti principali di una policy CSP. Specificano le fonti consentite per diversi tipi di risorse. Alcune delle direttive più comunemente usate includono:
- default-src: Imposta la fonte predefinita per tutti i tipi di risorse. È una direttiva di fallback che si applica quando non sono definite altre direttive più specifiche.
- script-src: Specifica le fonti consentite per JavaScript.
- style-src: Specifica le fonti consentite per i fogli di stile CSS.
- img-src: Specifica le fonti consentite per le immagini.
- font-src: Specifica le fonti consentite per i font.
- media-src: Specifica le fonti consentite per audio e video.
- object-src: Specifica le fonti consentite per plugin come Flash. (Generalmente è meglio evitare di consentire plugin, se possibile).
- frame-src: Specifica le fonti consentite per i frame (iframe).
- connect-src: Specifica le fonti consentite per le richieste di rete (AJAX, WebSockets).
- base-uri: Limita gli URL che possono essere utilizzati in un elemento
<base>. - form-action: Limita gli URL a cui i moduli possono essere inviati.
- frame-ancestors: Specifica i parent validi che possono incorporare una pagina usando
<frame>,<iframe>,<object>,<embed>, o<applet>. Questa direttiva fornisce protezione contro il Clickjacking. - upgrade-insecure-requests: Istruisce gli user agent a trattare tutti gli URL non sicuri di un sito (caricati su HTTP) come se fossero stati sostituiti con URL sicuri (caricati su HTTPS). Questa direttiva è pensata per i siti web che stanno migrando da HTTP a HTTPS.
- report-uri: Specifica un URL a cui il browser dovrebbe inviare i rapporti sulle violazioni della CSP. Obsoleto a favore di `report-to`.
- report-to: Specifica un nome di gruppo definito in un header `Report-To`. Ciò consente un controllo più granulare sulla segnalazione, inclusa la specifica di più endpoint di reporting.
Valori di Origine della CSP
I valori di origine definiscono le origini da cui è consentito caricare le risorse. Alcuni valori di origine comuni includono:
- *: Consente contenuti da qualsiasi fonte (Da evitare in produzione!).
- 'self': Consente contenuti dalla stessa origine (schema, host e porta) del documento protetto.
- 'none': Non consente contenuti da nessuna fonte.
- 'unsafe-inline': Consente l'uso di JavaScript e CSS inline (Da evitare in produzione!).
- 'unsafe-eval': Consente l'uso della valutazione dinamica del codice (es.
eval(),Function()) (Da evitare in produzione!). - 'strict-dynamic': Specifica che la fiducia data esplicitamente a uno script presente nel markup, accompagnandolo con un nonce o un hash, deve essere propagata a tutti gli script caricati da quell'antenato.
- 'unsafe-hashes': Consente specifici gestori di eventi inline. Questo è generalmente sconsigliato a causa della sua complessità e del beneficio limitato.
- data:: Consente il caricamento di risorse da URL di dati (es. immagini incorporate). Usare con cautela.
- mediastream:: Consente l'uso di URI `mediastream:` come fonte multimediale.
- blob:: Consente l'uso di URI `blob:` come fonte multimediale.
- filesystem:: Consente il caricamento di risorse da un filesystem.
- https://example.com: Consente contenuti da un dominio e una porta specifici.
- *.example.com: Consente contenuti da qualsiasi sottodominio di example.com.
- nonce-{random-value}: Consente script o stili con un attributo nonce corrispondente. Ciò richiede la generazione lato server di un valore nonce casuale per ogni richiesta.
- sha256-{hash-value}: Consente script o stili con un hash SHA256, SHA384 o SHA512 corrispondente.
Modalità CSP: Enforce vs. Report-Only
La CSP può essere implementata in due modalità:
- Modalità Enforce: In questa modalità, il browser blocca qualsiasi risorsa che violi la CSP. Questa è la modalità raccomandata per gli ambienti di produzione. La CSP viene inviata utilizzando l'header `Content-Security-Policy`.
- Modalità Report-Only: In questa modalità, il browser segnala le violazioni della CSP ma non blocca le risorse. Ciò è utile per testare e valutare una CSP prima di applicarla. La CSP viene inviata utilizzando l'header `Content-Security-Policy-Report-Only`.
Implementare la CSP: una Guida Passo-Passo
Implementare la CSP può sembrare complesso, ma seguendo un approccio strutturato, è possibile proteggere efficacemente la propria applicazione web.
1. Iniziare con una Policy in modalità Report-Only
Iniziate implementando una CSP in modalità report-only. Questo vi permette di monitorare le violazioni senza interrompere la funzionalità del vostro sito web. Configurate la direttiva report-uri o report-to per inviare i rapporti di violazione a un endpoint designato.
Esempio di header (Report-Only):
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report
2. Analizzare i Rapporti di Violazione
Analizzate attentamente i rapporti di violazione per identificare quali risorse vengono bloccate e perché. Questo vi aiuterà a comprendere le dipendenze delle risorse del vostro sito web e a identificare potenziali vulnerabilità di sicurezza.
I rapporti di violazione sono tipicamente inviati come payload JSON all'endpoint configurato con report-uri o report-to. Questi rapporti contengono informazioni sulla violazione, come l'URI bloccato, la direttiva violata e l'URI del documento.
3. Affinare la Policy CSP
Sulla base dei rapporti di violazione, affinate la vostra policy CSP per consentire le risorse legittime mantenendo al contempo una forte postura di sicurezza. Aggiungete valori di origine specifici per le risorse che vengono bloccate. Considerate l'uso di nonce o hash per gli script e gli stili inline per evitare di usare 'unsafe-inline'.
4. Passare alla modalità Enforce
Una volta sicuri che la vostra policy CSP non blocchi risorse legittime, passate alla modalità enforce. Questo bloccherà qualsiasi violazione rimanente e fornirà un robusto livello di sicurezza contro gli attacchi XSS.
Esempio di header (Enforce):
Content-Security-Policy: default-src 'self'; script-src 'self' https://example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report
5. Monitorare e Mantenere la Policy CSP
La CSP non è una soluzione "imposta e dimentica". È essenziale monitorare continuamente la vostra policy CSP e aggiornarla man mano che il vostro sito web evolve e emergono nuove minacce alla sicurezza. Rivedete regolarmente i rapporti di violazione e modificate la policy secondo necessità.
Esempi Pratici di CSP
Diamo un'occhiata ad alcuni esempi pratici di CSP per diversi scenari:
Esempio 1: CSP di base per un Sito Web Semplice
Questa CSP consente contenuti dalla stessa origine e immagini da qualsiasi fonte.
Content-Security-Policy: default-src 'self'; img-src *
Esempio 2: CSP con Fonti Specifiche per Script e Stili
Questa CSP consente script dalla stessa origine e da un CDN specifico, e stili dalla stessa origine e stili inline.
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'
Esempio 3: CSP con Nonce per Script Inline
Questa CSP richiede un nonce unico per ogni script inline.
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-r4nd0mn0nc3'
HTML:
<script nonce="r4nd0mn0nc3">console.log('Hello, world!');</script>
Importante: Il valore nonce deve essere generato dinamicamente sul server per ogni richiesta. Questo impedisce agli aggressori di riutilizzare il nonce.
Esempio 4: CSP che Limita i Frame Ancestors per Prevenire il Clickjacking
Questa CSP impedisce che la pagina venga incorporata in un iframe su qualsiasi dominio eccetto `https://example.com`.
Content-Security-Policy: frame-ancestors 'self' https://example.com
Esempio 5: Una CSP più restrittiva che usa 'strict-dynamic' e un fallback a 'self'
Questa CSP sfrutta `strict-dynamic` per i browser moderni, supportando al contempo i browser più vecchi che non lo supportano. Include anche un `report-uri` per il monitoraggio delle violazioni.
Content-Security-Policy: default-src 'self'; script-src 'strict-dynamic' 'nonce-{random-nonce}' 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report
Ricordate di sostituire `{random-nonce}` con un valore nonce generato dinamicamente lato server.
CSP e Single-Page Applications (SPA)
Implementare la CSP nelle SPA può essere impegnativo a causa della natura dinamica di queste applicazioni. Le SPA si basano spesso pesantemente su JavaScript per generare e manipolare il DOM, il che può portare a violazioni della CSP se non gestito con attenzione.
Ecco alcuni suggerimenti per implementare la CSP nelle SPA:
- Evitare
'unsafe-inline'e'unsafe-eval': Queste direttive dovrebbero essere evitate il più possibile nelle SPA. Indeboliscono significativamente la sicurezza della vostra applicazione. - Usare Nonce o Hash: Usate nonce o hash per gli script e gli stili inline. Questo è l'approccio raccomandato per le SPA.
- Considerare i Trusted Types: Trusted Types è un'API del browser che aiuta a prevenire le vulnerabilità XSS basate sul DOM. Può essere utilizzata in combinazione con la CSP per migliorare ulteriormente la sicurezza.
- Usare un framework compatibile con la CSP: Alcuni framework frontend (come React con configurazioni specifiche, Angular e Vue.js) forniscono funzionalità per aiutarvi a implementare la CSP più facilmente.
Altri Header di Sicurezza Frontend Importanti
Sebbene la CSP sia una pietra miliare della sicurezza frontend, altri header giocano un ruolo cruciale nel fornire una strategia di difesa completa:
Strict-Transport-Security (HSTS)
L'header Strict-Transport-Security (HSTS) istruisce il browser a usare sempre HTTPS per connettersi al sito web. Questo previene attacchi man-in-the-middle che tentano di declassare la connessione a HTTP.
Esempio di header:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
max-age: Specifica la durata (in secondi) per cui il browser dovrebbe ricordare di accedere al sito solo tramite HTTPS. Un valore di 31536000 secondi (1 anno) è raccomandato per gli ambienti di produzione.includeSubDomains: Indica che la policy HSTS si applica a tutti i sottodomini del dominio.preload: Consente al dominio di essere incluso in un elenco di domini abilitati HSTS che è precaricato nei browser. Ciò richiede l'invio del proprio dominio alla lista di preload HSTS gestita da Google.
X-Frame-Options
L'header X-Frame-Options previene gli attacchi di clickjacking controllando se il sito web può essere incorporato in un iframe.
Esempio di header:
X-Frame-Options: DENY
Valori possibili:
DENY: Impedisce che la pagina venga visualizzata in un iframe, indipendentemente dall'origine.SAMEORIGIN: Consente la visualizzazione della pagina in un iframe solo se l'origine dell'iframe corrisponde all'origine della pagina.ALLOW-FROM uri: Consente la visualizzazione della pagina in un iframe solo se l'origine dell'iframe corrisponde all'URI specificato. Nota: Questa opzione è obsoleta e potrebbe non essere supportata da tutti i browser.
Nota: La direttiva frame-ancestors nella CSP fornisce un modo più flessibile e potente per controllare l'incorporamento ed è generalmente preferita a X-Frame-Options.
X-XSS-Protection
L'header X-XSS-Protection abilita il filtro XSS integrato del browser. Sebbene la CSP sia una soluzione più robusta per prevenire gli attacchi XSS, questo header può fornire un ulteriore livello di difesa, specialmente per i browser più vecchi che potrebbero non supportare pienamente la CSP.
Esempio di header:
X-XSS-Protection: 1; mode=block
1: Abilita il filtro XSS.0: Disabilita il filtro XSS.mode=block: Istruisce il browser a bloccare la pagina se viene rilevato un attacco XSS.report=uri: Specifica un URL a cui il browser dovrebbe inviare un rapporto se viene rilevato un attacco XSS.
Referrer-Policy
L'header Referrer-Policy controlla la quantità di informazioni sul referrer che viene inviata con le richieste. Le informazioni sul referrer possono essere utilizzate per tracciare gli utenti tra i siti web, quindi controllarle può migliorare la privacy dell'utente.
Esempio di header:
Referrer-Policy: strict-origin-when-cross-origin
Alcuni valori comuni:
no-referrer: Non inviare mai l'header Referer.no-referrer-when-downgrade: Non inviare l'header Referer a origini senza TLS (HTTPS).origin: Invia solo l'origine (schema, host e porta) nell'header Referer.origin-when-cross-origin: Invia l'origine per le richieste cross-origin e l'URL completo per le richieste same-origin.same-origin: Invia l'header Referer per le richieste same-origin, ma non per le richieste cross-origin.strict-origin: Invia solo l'origine quando il livello di sicurezza del protocollo rimane lo stesso (da HTTPS a HTTPS), ma non inviare alcun header a una destinazione meno sicura (da HTTPS a HTTP).strict-origin-when-cross-origin: Invia l'origine quando si esegue una richiesta same-origin. Per le richieste cross-origin, invia l'origine solo quando il livello di sicurezza del protocollo rimane lo stesso (da HTTPS a HTTPS), ma non inviare alcun header a una destinazione meno sicura (da HTTPS a HTTP).unsafe-url: Invia l'URL completo nell'header Referer, indipendentemente dall'origine. Usare con estrema cautela, poiché ciò può esporre informazioni sensibili.
Permissions-Policy (precedentemente Feature-Policy)
L'header Permissions-Policy (precedentemente noto come Feature-Policy) permette agli sviluppatori di abilitare e disabilitare selettivamente le funzionalità e le API del browser. Questo può aiutare a ridurre la superficie di attacco della vostra applicazione e a migliorare la privacy dell'utente.
Esempio di header:
Permissions-Policy: geolocation=()
Questo esempio disabilita l'API di geolocalizzazione per il sito web.
Altre funzionalità che possono essere controllate con Permissions-Policy includono:
cameramicrophonegeolocationaccelerometergyroscopemagnetometerusbmidipaymentfullscreen
Impostare gli Header di Sicurezza su Piattaforme Diverse
Il metodo per impostare gli header di sicurezza varia a seconda del server web o della piattaforma che si sta utilizzando. Ecco alcuni esempi comuni:
Apache
È possibile impostare gli header di sicurezza in Apache aggiungendoli al file .htaccess o al file di configurazione del server (httpd.conf).
Esempio di configurazione .htaccess:
<IfModule mod_headers.c>
Header set Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report"
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header set X-Frame-Options "DENY"
Header set X-XSS-Protection "1; mode=block"
Header set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
Nginx
È possibile impostare gli header di sicurezza in Nginx aggiungendoli al blocco server nel file di configurazione di Nginx (nginx.conf).
Esempio di configurazione Nginx:
server {
listen 443 ssl;
server_name example.com;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; report-uri /csp-report";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header X-Frame-Options "DENY";
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin-when-cross-origin";
...
}
Node.js (Express)
È possibile impostare gli header di sicurezza in Node.js utilizzando middleware come Helmet.
Esempio usando Helmet:
const express = require('express');
const helmet = require('helmet');
const app = express();
app.use(helmet());
// Personalizza la CSP se necessario
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://cdn.example.com"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:"],
reportUri: '/csp-report'
},
}));
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Server in ascolto sulla porta 3000');
});
Cloudflare
Cloudflare consente di impostare gli header di sicurezza utilizzando le Page Rules o le Transform Rules.
Testare i Propri Header di Sicurezza
Dopo aver implementato gli header di sicurezza, è fondamentale testarli per assicurarsi che funzionino correttamente. Diversi strumenti online possono aiutarvi ad analizzare gli header di sicurezza del vostro sito web:
- SecurityHeaders.com: Uno strumento semplice ed efficace per l'analisi degli header di sicurezza.
- Mozilla Observatory: Uno strumento completo per testare la sicurezza dei siti web, inclusi gli header di sicurezza.
- WebPageTest.org: Permette di visualizzare gli header HTTP nel grafico a cascata (waterfall chart).
Conclusione
Gli header di sicurezza frontend, in particolare la Content Security Policy (CSP), sono essenziali per proteggere le applicazioni web da vari attacchi e migliorare la sicurezza degli utenti. Implementando e mantenendo attentamente questi header, è possibile ridurre significativamente il rischio di XSS, clickjacking e altre vulnerabilità di sicurezza. Ricordate di iniziare con una policy in modalità report-only, analizzare i rapporti di violazione, affinare la policy e quindi passare alla modalità enforce. Monitorate e aggiornate regolarmente i vostri header di sicurezza per mantenere il vostro sito web sicuro man mano che evolve e emergono nuove minacce.
Adottando un approccio proattivo alla sicurezza frontend, potete costruire applicazioni web più sicure e affidabili che proteggono i vostri utenti e la vostra azienda.